import { BaseServices } from "./base.services";
import { Uri, Method, RespInfo, config } from "./config";
import { chatDB } from "@/db/chat";
import { KeyValue, SessionInfo } from "@/models/@types";
import { AIDrawMenuInfo } from "@/models/aidraw";
import { appContext } from "@/models/app.context";
import { AppRef } from "@/models/app.ref";
import { ChatWorkMenuInfo } from "@/models/chat-work";

// 功能模块key
export type SyncModuleEnum = "chat-aidraw" | "chat-file" | "chat-work" | "chat-mindmap" | "online-search" | "chat-prompts";
const keys = ["chat-aidraw", "chat-file", "chat-work", "chat-mindmap", "online-search", "chat-prompts"];

export type SyncSessionInfo = {
  id: string;
  value: string;
  module: string;
  parent?: string; //
  weight?: number; // 权重
  messages?: SyncMessageInfo[];
};
export type SyncMessageInfo = {
  id: string;
  value: string;
};
export enum SyncActionEnum {
  Add = 1,
  Delete = 2,
  Update = 3,
}
class SynchronousService extends BaseServices {
  private keys: string[] = [];
  private _appRef: AppRef;
  public LOCAL_STORAGE_UP_KEY = "sync_up_key";
  private sync_up_keys: string[] = [];

  private static _ins: SynchronousService = new SynchronousService();
  public static get ins(): SynchronousService {
    return this._ins ? this._ins : (this._ins = new SynchronousService());
  }

  constructor() {
    super();
    this.init();
  }

  async init(): Promise<void> {
    const appRef: any = (await import("@/models/app.ref")).appRef;
    this._appRef = appRef;
    this.keys = [appRef.chatWork.LOCAL_STORAGE_KEY, appRef.aidraw.LOCAL_STORAGE_KEY, appRef.chatFile.LOCAL_STORAGE_KEY, appRef.mindMap.LOCAL_STORAGE_KEY, appRef.prompt.LOCAL_STORAGE_KEY, appRef.onlineSearch.LOCAL_STORAGE_KEY];
  }

  /** 同步本地数据至云 */
  public async up(): Promise<void> {
    const list = [];
    for (const key of this.keys) {
      const item = await chatDB.getStr(key);
      if (item) list.push(item);
    }
    const url = config.usersbeasking + Uri.Synchronous + Method.Up;
    const data = { list };
    return new Promise<void>((resolve) => {
      if (!appContext.global.token) {
        resolve();
        return;
      }
      this.request(url, data).then(() => {
        resolve();
      });
    });
  }
  /** 注册时全量同步至云 */
  public async allUp(): Promise<void> {
    this.sync_up_keys = JSON.parse(localStorage.getItem(this.LOCAL_STORAGE_UP_KEY) || "[]");
    console.log('sync_up_keys', this.sync_up_keys);
    const list = [];
    console.log(keys);
    for (const key of keys) {
      const item = await chatDB.getStr(key);
      if (item) list.push(item);
    }
    console.log(list);
    await Promise.all(
      list.map((item) => {
        return new Promise<void>(async (resolve) => {
          const menus = JSON.parse(item?.value || "{}")?.menus || [];
          console.log(item.key, menus);
          for (const menu of menus || []) {
            await this.session(item.key, SyncActionEnum.Add, menu).then(async () => {
              await menu.sessions?.map(async (message) => await this.message(SyncActionEnum.Add, menu.uid, message));
            });
            for (const child of menu?.childrens || []) {
              await this.session(item.key, SyncActionEnum.Add, child, menu.uid).then(async () => {
                await child.sessions?.map(async (message) => await this.message(SyncActionEnum.Add, child.uid, message));
              });
            }
          }
          resolve();
        });
      })
    );
    localStorage.setItem(this.LOCAL_STORAGE_UP_KEY, JSON.stringify([...new Set(this.sync_up_keys)]));
  }

  /** 增量同步session至云 */
  public async session(module: string, action: SyncActionEnum, menu: ChatWorkMenuInfo | AIDrawMenuInfo, parent?: string): Promise<void> {
    const session: SyncSessionInfo = { id: menu.uid, module, value: JSON.stringify(menu) };
    const url = config.usersbeasking + Uri.Dev + Uri.Synchronous + Method.Session;
    const data = { action, session, parent };
    return new Promise<void>((resolve) => {
      if (!appContext.global.token || (action === SyncActionEnum.Add && this.sync_up_keys?.includes(session.id))) {
        resolve();
        return;
      }
      this.request(url, data).then(() => {
        action === SyncActionEnum.Add ? this.sync_up_keys?.push(session.id) : null;
        resolve();
      });
    });
  }
  /** 清空 某个模块下的所有会话 */
  public async clearSession(module: string): Promise<void> {
    const url = config.usersbeasking + Uri.Dev + Uri.Synchronous + Method.Session + "/" + Method.Clear;
    const data = { module };
    return new Promise<void>((resolve) => {
      if (!appContext.global.token) {
        resolve();
        return;
      }
      this.request(url, data).then(() => {
        localStorage.removeItem(this.LOCAL_STORAGE_UP_KEY);
        resolve();
      });
    });
  }
  /** 增量同步message至云 */
  public async message(action: SyncActionEnum, session: string, info: SessionInfo): Promise<void> {
    const message = { id: info.uid, value: JSON.stringify(info) };
    const url = config.usersbeasking + Uri.Dev + Uri.Synchronous + Method.Message;
    const data = { action, session, message };
    return new Promise<void>((resolve) => {
      if (!appContext.global.token || (action === SyncActionEnum.Add && this.sync_up_keys?.includes(message.id))) {
        resolve();
        return;
      }
      this.request(url, data).then(() => {
        action === SyncActionEnum.Add ? this.sync_up_keys?.push(message.id) : null;
        resolve();
      });
    });
  }

  /** 同步云数据至本地 */
  public async down(): Promise<void> {
    const url = config.usersbeasking + Uri.Dev + Uri.Synchronous + Method.Down;
    const data = {};
    return new Promise<void>(async (resolve) => {
      if (!appContext.global.token) {
        resolve();
        return;
      }
      await this.allUp();
      this.request(url, data)
        .then(async (res: RespInfo<KeyValue<string, SyncSessionInfo[]>>) => {
          Promise.all(
            res?.list?.map(async (item) => {
              return new Promise<void>(async (resolve1) => {
                await chatDB.set(item.key, "");
                const menus = item.value?.map((val) => {
                  const sessions = val.messages?.map((message) => JSON.parse(message.value));
                  const info = JSON.parse(val.value);
                  info.sessions = sessions || [];
                  return info;
                });
                const str = { currKey: menus[0].uid, menus };
                await chatDB.set(item.key, JSON.stringify(str));
                resolve1();
              });
            })
          );
          console.log("同步云数据至本地 success");
          resolve();
        })
        .catch(() => resolve());
    });
  }
}

export const synchronousService: SynchronousService = SynchronousService.ins;
